<?php
namespace App\Admin\Controllers\SalesReport;

use App\Models\Basics\AmazonCountry;
use App\Models\Basics\SysArea;
use App\Models\SalesReport\PaymentClassify;
use App\Models\Product\ProductClassify;
use App\Util\ReportPermission;
use App\Util\User;
use Encore\Admin\Controllers\AdminController;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
class PaymentSummaryController extends AdminController{

    protected $title = '月利润汇总报表';

    protected $filters = [
        'start_date' => null,
        'end_date' => null,
        'summary' => null,
        'dimension' => null,
        'with_classify' => null,
        'area_id' => [],
        'country_id' => [],
        'seller_id' => [],
        'season' => null,
        'classify_id' => [],
        'type' => null,
    ];

    protected function grid()
    {
        $filtersField = array_keys($this->filters);
        $filters = $this->_getFilters($filtersField);
        $this->_initFilters($filters);
        $summary = $filters['summary'];
        $dimension = $filters['dimension'];
        $withClassify = $filters['with_classify'];
        $modelStr = $this->_model($summary,$dimension,$withClassify);
        $permissionStr = $this->_permission($dimension);
        $filtersArr = $this->_filtersArr($summary,$dimension,$withClassify);
        $query = $this->_initQuery($modelStr,$permissionStr,$filters,$filtersArr,$withClassify);
        $_query = clone $query;
        $headers = $modelStr::headersField();
        $groupByArr = $this->_groupBy($summary,$dimension,$withClassify);
        $paginator = $this->_paginator($query,$headers,$groupByArr);
        $total = $this->_sum($_query,$headers);
        $action = getAction($filtersField);
        $filtersBlade = [];
        $filtersBlade['start_date'] = $this->filters['start_date'];
        $filtersBlade['end_date'] = $this->filters['end_date'];
        $filtersBlade['summary'] = $this->filters['summary'];
        $filtersBlade['dimension'] = $this->filters['dimension'];
        $filtersBlade['with_classify'] = $this->filters['with_classify'];
        $filtersBlade['area_id'] = getMultipleOptions(SysArea::options(),$this->filters['area_id']);
        $filtersBlade['country_id'] = getMultipleOptions(AmazonCountry::options(),$this->filters['country_id']);
        $filtersBlade['seller_id'] = getMultipleOptions(User::getCSellerOptions(),$this->filters['seller_id']);
        $filtersBlade['season'] = getOptions(ProductClassify::$_season,$this->filters['season']);
        $filtersBlade['classify_id'] = getMultipleOptions(ProductClassify::options(),$this->filters['classify_id']);
        $filtersBlade['type'] = getOptions(PaymentClassify::$_type,$this->filters['type']);
        $downloadUrl = '/xqc/sales-report/payment-summary-download?' . http_build_query(array_merge(Request::all(),['_export_' => true]));
        $viewWithClassify = $this->_viewWithClassify($withClassify);
        $viewList = $this->_viewList($summary,$dimension);
        $viewType = $this->_viewType();

        return view('sales-report.payment-summary.index', compact('viewWithClassify','viewList','viewType','paginator','total','headers','filtersBlade','action','downloadUrl'));
    }

    private function _model($summary,$dimension,$withClassify){
        $modelWithClassify = $withClassify == 1 ? 'PaymentC' : 'PaymentT'; //头缀模型名称
        if($dimension == 1){
            $modelDimension = 'A'; //站点
        }elseif($dimension == 2){
            $modelDimension = 'C'; //国家
        }elseif($dimension == 3){
            $modelDimension = 'S'; //销售
        }else{
            $modelDimension = 'N'; //无
        }
        $modelSummary = $summary == 1 ? 'Summary' : 'Detail'; //尾缀模型名称
        $model = '\\App\\Models\\SalesReport\\'.$modelWithClassify.$modelDimension.$modelSummary;
        return $model;
    }

    private function _permission($dimension){
        if($dimension == 4)return 'none';
        if($dimension == 1){
            $permission = 'area';
        }elseif($dimension == 2){
            $permission = 'country';
        }else{
            $permission = 'seller';
        }
        return $permission;
    }

    private function _filtersArr($summary,$dimension,$withClassify){
        if($dimension == 4){
            return $withClassify == 1 ? ['classify_id'] : [];
        }
        if($withClassify == 1){
            if($summary == 1){
                if($dimension == 1){
                    $filters = ['area_id','classify_id'];
                }elseif($dimension == 2){
                    $filters = ['country_id','classify_id'];
                }else{
                    $filters = ['seller_id','classify_id'];
                }
            }else{
                if($dimension == 1){
                    $filters = ['area_id','classify_id'];
                }elseif($dimension == 2){
                    $filters = ['area_id','country_id','classify_id'];
                }else{
                    $filters = ['area_id','country_id','seller_id','classify_id'];
                }
            }
        }else{
            if($summary == 1){
                if($dimension == 1){
                    $filters = ['area_id'];
                }elseif($dimension == 2){
                    $filters = ['country_id'];
                }else{
                    $filters = ['seller_id'];
                }
            }else{
                if($dimension == 1){
                    $filters = ['area_id'];
                }elseif($dimension == 2){
                    $filters = ['area_id','country_id'];
                }else{
                    $filters = ['area_id','country_id','seller_id'];
                }
            }
        }
        return $filters;
    }

    private function _viewWithClassify($withClassify){
        return $withClassify == 1 ? 'list-with-classify' : 'list-no-classify';
    }

    private function _viewList($summary,$dimension){
        if($summary == 1){
            if($dimension == 1){
                $list = 'area-summary';
            }elseif($dimension == 2){
                $list = 'country-summary';
            }elseif($dimension == 3){
                $list = 'seller-summary';
            }else{
                $list = 'none-summary';
            }
        }else{
            if($dimension == 1){
                $list = 'area-detail';
            }elseif($dimension == 2){
                $list = 'country-detail';
            }elseif($dimension == 3){
                $list = 'seller-detail';
            }else{
                $list = 'none-detail';
            }
        }
        return $list;
    }

    private function _viewType(){
        $type = request('type');
        if($type == 1){
            return 'list-num';
        }elseif($type == 2){
            return 'list-per';
        }else{
            return 'list';
        }
    }

    private function _getFilters($filtersField){
        $startDate = request('start_date');
        $endDate = request('end_date');
        $reportDate = $this->__reportDate($startDate,$endDate);
        $filters = [];
        foreach ($filtersField as $field){
            if(array_key_exists($field,$reportDate)){
                $filters[$field] = $reportDate[$field];
            }elseif(in_array($field,['summary','dimension','with_classify'])){
                $filters[$field] = request($field,1);
            }elseif(in_array($field,['area_id','country_id','seller_id','classify_id'])){
                $filters[$field] = request($field,[]);
            }else{
                $filters[$field] = request($field);
            }
        }
        return $filters;
    }

    private function __reportDate($start,$end){
        if(is_null($start) && is_null($end)){
            $time = strtotime("midnight first day of -1 month");
            $startDate = $endDate = date('Y-m-01',$time);
        }elseif(!is_null($start) && is_null($end)){
            $startDate = $endDate = $start;
        }elseif(is_null($start) && !is_null($end)){
            $startDate = $endDate = $end;
        }else{
            $startDate = $start;
            $endDate = $end;
        }
        return ['start_date' => $startDate,'end_date' => $endDate];
    }

    private function _initFilters($filters){
        foreach ($filters as $field => $filter){
            $this->filters[$field] = $filter;
        }
    }

    private function _initQuery($model,$permission,$filters,$filtersArr,$withClassify){
        $query = $model::query();
        if($permission != 'none'){
            $query = ReportPermission::{$permission}($query);
        }
        if($withClassify == 1){
            $query = ReportPermission::classifyRClassify($query);
        }
        foreach ($filters as $field => $filter){
            if(!$filter)continue;
            if($field == 'start_date'){
                $query->where('report_date','>=',$filter);
            }
            if($field == 'end_date'){
                $query->where('report_date','<=',$filter);
            }
            if($withClassify == 1 && $field == 'season'){
                $query->whereHas('classify', function ($query) use($filter){
                    $query->where('season', $filter);
                });
            }
            if(!empty($filtersArr) && in_array($field,$filtersArr)){
                $query->whereIn($field,$filter);
            }
        }
        return $query;
    }

    private function _groupBy($summary,$dimension,$withClassify){
        if($dimension == 4){
            if($summary == 1){
                return $withClassify == 1 ? ['classify_id'] : ['none_flag'];
            }else{
                return [];
            }
        }
        if($withClassify == 1){
            if($summary == 1){
                if($dimension == 1){
                    $groupBy = ['area_id','classify_id'];
                }elseif($dimension == 2){
                    $groupBy = ['country_id','classify_id'];
                }else{
                    $groupBy = ['seller_id','classify_id'];
                }
            }else{
                if($dimension == 1){
                    $groupBy = ['area_id','classify_id','report_date'];
                }elseif($dimension == 2){
                    $groupBy = ['country_id','classify_id','report_date'];
                }else{
                    $groupBy = [];
                }
            }
        }else{
            if($summary == 1){
                if($dimension == 1){
                    $groupBy = ['area_id'];
                }elseif($dimension == 2){
                    $groupBy = ['country_id'];
                }else{
                    $groupBy = ['seller_id'];
                }
            }else{
                $groupBy = [];
            }
        }
        return $groupBy;
    }

    private function _paginator($query,$headers,$groupByArr){
        if(!empty($groupByArr)){
            $query->selectRaw($this->__getFields($headers,$groupByArr))->groupBy($groupByArr);
        }
        return $query->paginate((int) (request("per_page",10)))->appends(Request::input());
    }

    private function __getFields($headers,$groupByArr){
        $re = '';
        foreach ($headers as $field => $item){
            if($item['sumField']){
                $re .= 'sum('.$field.') as '.$field.',';
            }else{
                if (isset($item['continue']) && !$item['continue']){
                    $re .= 'min('.$field.') as '.$field.',';
                }
            }
        }
        return $re.implode(',',$groupByArr);
    }

    private function _sum($query,$headers){
        $sum = $query->selectRaw($this->__getSumFields($headers))->groupBy(1)->first();
        return $sum ? $sum->toArray() : $this->__getSumFieldsInit($headers);
    }

    private function __getSumFields($headers){
        $re = '';
        foreach ($headers as $field => $item){
            if($item['sumField']){
                $re .= 'sum('.$field.') as '.$field.',';
            }
        }
        return $re.'1';
    }

    private function __getSumFieldsInit($headers){
        $re = [];
        foreach ($headers as $field => $item){
            if($item['sumField']){
                $re[$field] = 0;
            }
        }
        return $re;
    }

    public function download(){
        $filtersField = array_keys($this->filters);
        $filters = $this->_getFilters($filtersField);
        $summary = $filters['summary'];
        $dimension = $filters['dimension'];
        $withClassify = $filters['with_classify'];
        $modelStr = $this->_model($summary,$dimension,$withClassify);
        $permissionStr = $this->_permission($dimension);
        $filtersArr = $this->_filtersArr($summary,$dimension,$withClassify);
        $query = $this->_initQuery($modelStr,$permissionStr,$filters,$filtersArr,$withClassify);
        $headers = $modelStr::headersField();
        $groupByArr = $this->_groupBy($summary,$dimension,$withClassify);
        if(!empty($groupByArr)){
            $query->selectRaw($this->__getFields($headers,$groupByArr))->groupBy($groupByArr);
        }
        $orderBy = $this->_orderBy($summary,$dimension,$withClassify);
        $query->orderBy($orderBy,'DESC');
        $downloadType = $this->_downloadType();
        $head = Arr::pluck($headers,'title');
        $this->_exeDownload($modelStr,$head,$query,$downloadType);
    }

    private function _orderBy($summary,$dimension,$withClassify){
        if($dimension == 4){
            if($summary == 1){
                return $withClassify == 1 ? 'classify_id' : 'sales_volume';
            }else{
                return 'id';
            }
        }
        if($withClassify == 1){
            if($dimension == 3){
                if($summary == 1){
                    $orderBy = 'seller_id';
                }else{
                    $orderBy = 'id';
                }
            }elseif($dimension == 1){
                $orderBy = 'area_id';
            }else{
                $orderBy = 'country_id';
            }
        }else{
            if($summary == 1){
                if($dimension == 1){
                    $orderBy = 'area_id';
                }elseif($dimension == 2){
                    $orderBy = 'country_id';
                }else{
                    $orderBy = 'seller_id';
                }
            }else{
                $orderBy = 'id';
            }
        }
        return $orderBy;
    }

    private function _downloadType(){
        $type = request('type');
        if($type == 1){
            return 'getDownloadNumData';
        }elseif($type == 2){
            return 'getDownloadPerData';
        }else{
            return 'getDownloadData';
        }
    }

    private function _exeDownload($modelStr,$head,$query,$downloadType){
        set_time_limit(0);
        $response = new StreamedResponse(null, 200, [
            'Content-Type'        => 'text/csv;charset=utf-8',
            'Content-Disposition' => 'attachment;filename="月利润汇总报表.csv"',
        ]);
        $response->setCallback(function () use ($modelStr,$head,$query,$downloadType) {
            $fp = fopen('php://output', 'w');
            fwrite($fp, chr(0xEF).chr(0xBB).chr(0xBF));
            fputcsv($fp, $head);
            $query->chunk(800, function ($re) use ($fp,$modelStr,$downloadType){
                $data = $modelStr::{$downloadType}($re);
                foreach ($data as $item) {
                    fputcsv($fp, $item);
                }
            });
            fclose($fp);
        });
        $response->send();
        exit(0);
    }
}
